<template>
    <view class="py-outer-content">
        <view class="py-list-content">
            <u-tabs :list="tabsList" @click="handleTabsClick"></u-tabs>
        </view>
        <!-- 表单信息 -->
        <view class="py-list-content py-flow-content" v-if="formShow"
            :style="{height: windowHeight ? 'calc('+ windowHeight + ' - 10rpx - 10rpx - 44px - 5px)' : ''}">
            <view class="py-content" style="margin-bottom: 10rpx;">
                <!-- #ifdef H5 -->
                <component :is="currentComponent" ref="currentComponent" :formData="componentForm"
                    :readOnly="!hasFillNode"></component>
                <!-- #endif -->

                <!-- #ifdef MP-WEIXIN || APP-PLUS -->
                <!-- 使用APP需要在main.js进行配置，配置位置有注释标注 -->
                <!-- 由于微信不支持动态组件，需要在pages.json中两处进行配置，配置位置有注释标注 -->
                <!-- 新增组件，只需要修改组件名称和最后条件判断中实际路径即可，并且将v-if替换成v-else-if -->
                <!-- ref、formData和readOnly的内容均不能修改 -->
                <!-- 条件判断中要写详细文件路径，包含前缀@和后缀.vue -->
                <!-- v-if="'@/pages/py/test.vue' == currentComponentPath" -->
                <test ref="currentComponent" v-if="'@/pages/py/test.vue' == currentComponentPath"
                    :formData="componentForm" :readOnly="!hasFillNode"></test>
                <!-- #endif -->

                <!-- 操作 -->
                <u-line></u-line>
                <view style="margin: 5rpx 0 5rpx 0;">

                    <u-row justify="center" :gutter="4" v-if="loginUserId == startUserId && hasFillNode">
                        <u-col :span="4">
                            <u-button type="primary" text="保存" @click="submitCurrentForm(false)"></u-button>
                        </u-col>
                        <u-col :span="4">
                            <u-button type="success" text="发起" @click="submitCurrentForm(true)"></u-button>
                        </u-col>
                    </u-row>


                    <u-row justify="center" :gutter="3" v-else>
                        <!-- u-button在H5页面会自动调用第四个按钮的click，很奇怪的问题 -->
                        <!-- 开始以为是自己设置问题，把按钮位置调换后，发现第四个位置的按钮，会在页面加载时自动调用第四个按钮 -->
                        <!-- 但是，在微信小程序和APP中使用没有任何问题 -->
                        <!-- 由于上述问题，统一使用py-button，其实和u-button一样，只是初始化时不会调用@click -->
                        <!-- 只有按钮过多时才使用py-button，其他情况均使用u-button -->
                        <u-col :span="3">
                            <py-button type="primary" text="审批" @click="handleComplete"></py-button>
                        </u-col>
                        <u-col :span="3">
                            <py-button type="warning" text="选择退回" @click="handleReturn"></py-button>
                        </u-col>
                        <u-col :span="3">
                            <py-button type="error" text="退回上级" @click="handleReject"></py-button>
                        </u-col>
                        <u-col :span="3">
                            <py-button type="error" text="退回初始" @click="handleReturnFirst"></py-button>
                        </u-col>
                    </u-row>

                </view>

            </view>

        </view>

        <!-- 流转记录 -->
        <view class="py-list-content py-flow-content" v-else-if="flowRecordShow"
            :style="{height: windowHeight ? 'calc('+ windowHeight + ' - 10rpx - 10rpx - 44px - 5px)' : ''}">
            <view class="py-content">
                <!-- 非初始节点 -->
                <view v-for="(item, index) in flowRecordList" :key="index">
                    <py-flow-record-item :flow="item" fillNode :firstAssigneeName="lastFlowRecord.assigneeName"
                        :firstDeptName="lastFlowRecord.deptName"
                        v-if="item.taskDefKey == lastFlowRecord.taskDefKey"></py-flow-record-item>
                    <py-flow-record-item :flow="item" v-else></py-flow-record-item>
                </view>
                <!-- 初始节点设置 -->
                <py-flow-record-item :flow="lastFlowRecord" start></py-flow-record-item>
            </view>
        </view>


        <!-- 流程图 -->
        <view class="py-flow-content" v-else-if="flowableShow"
            :style="{height: windowHeight ? 'calc('+ windowHeight + ' - 10rpx - 44px - 5px)' : ''}">
            <py-bpmn-viewer :flowData="flowData"></py-bpmn-viewer>
        </view>

        <!-- 审批弹框 -->
        <py-popup :show="completeOpen" mode="center" @close="completeOpen = false;" title="流程审批">
            <template slot="form">
                <view>
                    <py-section title="处理意见">
                        <u--textarea v-model="comment" placeholder="请填写处理意见" autoHeight></u--textarea>
                    </py-section>
                    <view class="py-popup-button-group">
                        <u-button type="primary" text="审批" @click="taskComplete"></u-button>
                        <u-button type="warning" text="取消" @click="completeOpen = false;"></u-button>
                    </view>

                </view>
            </template>

        </py-popup>


        <!-- 选择退回弹框 -->
        <py-popup :show="returnOpen" mode="center" @close="returnOpen = false;" title="退回流程">
            <template slot="form">
                <view>
                    <py-section title="退回节点">
                        <view class="py-return-tag-group">
                            <py-tag :text="item.name" :plain="!(returnTaskActiveId == item.id)"
                                :borderColor="returnTaskActiveId == item.id ? '#5ac725' : '#c8c9cc'"
                                :bgColor="returnTaskActiveId == item.id ? '#5ac725' : ''"
                                :color="returnTaskActiveId == item.id ? 'white' : '#606266'" :name="item.id"
                                @click="handleReturnTagClick" v-for="(item, index) in returnTaskList" :key="item.id">
                            </py-tag>
                        </view>
                    </py-section>


                    <py-section title="处理意见">
                        <u--textarea v-model="comment" placeholder="请填写处理意见" autoHeight></u--textarea>
                    </py-section>
                    <view class="py-popup-button-group">
                        <u-button type="primary" text="退回" @click="taskReturn"></u-button>
                        <u-button type="warning" text="取消" @click="returnOpen = false;"></u-button>
                    </view>

                </view>
            </template>

        </py-popup>


        <!-- 退回上级弹框 -->
        <py-popup :show="rejectOpen" mode="center" @close="rejectOpen = false;" title="驳回流程">
            <template slot="form">
                <view>
                    <py-section title="驳回意见">
                        <u--textarea v-model="comment" placeholder="请填写驳回意见" autoHeight></u--textarea>
                    </py-section>
                    <view class="py-popup-button-group">
                        <u-button type="primary" text="驳回" @click="taskReject"></u-button>
                        <u-button type="warning" text="取消" @click="rejectOpen = false;"></u-button>
                    </view>
                </view>
            </template>

        </py-popup>

        <!-- 退回初始 -->
        <py-popup :show="returnFirstOpen" mode="center" @close="returnFirstOpen = false;" title="退回初始流程">
            <template slot="form">
                <view>
                    <py-section title="退回意见">
                        <u--textarea v-model="comment" placeholder="请填写退回意见" autoHeight></u--textarea>
                    </py-section>
                    <view class="py-popup-button-group">
                        <u-button type="primary" text="退回" @click="taskFirstReturn"></u-button>
                        <u-button type="warning" text="取消" @click="returnFirstOpen = false;"></u-button>
                    </view>
                </view>
            </template>
        </py-popup>


        <!-- 消息提醒框 -->
        <!-- 由于py-popup的z-index值太大，会隐藏uni.showToast的显示，所以用u-toast进行消息提醒 -->
        <u-toast ref="uToast"></u-toast>
    </view>

</template>
<script>
    import { getBpmnStartId } from "@/api/flowable/py";
    import store from "@/store";
    import { flowRecord } from "@/api/flowable/finished";
    import {
        getFormVariableList,
        updateFormVariableList
    } from "@/api/flowable/flowableFormVariable";
    import {
        getFlowableFormByDeployId
    } from "@/api/flowable/flowableForm";
    import {
        complete,
        getNextFlowNode,
        returnList,
        returnTask,
        rejectTask
    } from "@/api/flowable/todo";
    import {
        flowXmlAndNode
    } from "@/api/flowable/definition";
    import {
        getWindowHeight,
        getVarType,
        getFormData
    } from "@/utils/py";
    export default {
        data() {
            return {
                // 标签列表信息
                tabsList: [
                    {
                        name: "表单信息"
                    },
                    {
                        name: "流转记录"
                    },
                    {
                        name: "流程图"
                    }
                ],
                // 是否展示表单信息
                formShow: true,
                // 是否展示流转记录
                flowRecordShow: false,
                // 是否展示流程图
                flowableShow: false,

                // 模型xml数据
                flowData: {},
                // 查询参数
                queryParams: {
                    deptId: undefined
                },
                deployId: "", // 流程定义编号
                procInsId: "", // 流程实例编号
                taskId: "", // 任务编号

                flowRecordList: [], // 流程流转数据

                // 流程图对应的id
                procDefId: undefined,

                // 是否填写节点
                hasFillNode: false,

                // 发起人id
                startUserId: undefined,

                // 登录账号id
                loginUserId: undefined,

                // 最后一个流程记录，也就是流程开始节点信息
                lastFlowRecord: undefined,

                // 当前组件
                // #ifdef APP-PLUS || H5
                currentComponent: undefined,
                // #endif

                // #ifdef APP-PLUS
                // App组件路径
                currentAppComponentPath: "",
                // #endif

                // 表单Id
                formId: undefined,

                // 是否启动流程
                hasStart: false,

                // 窗口高度（去掉导航栏）
                windowHeight: undefined,

                // 当前组件路径
                // #ifdef MP-WEIXIN || APP-PLUS
                currentComponentPath: "",
                // #endif

                // 是否启动流程
                hasStart: false,

                // 组件表单
                componentForm: undefined,


                // 任务信息
                taskForm: {
                    returnTaskShow: false, // 是否展示回退表单
                    delegateTaskShow: false, // 是否展示回退表单
                    defaultTaskShow: true, // 默认处理
                    comment: "", // 意见内容
                    variables: {},
                    // 表单数据
                    itemList: []
                },

                // 表单id对象
                formIdObj: {},

                // 审批弹窗是否打开
                completeOpen: false,


                // 选择退回弹框是否打开
                returnOpen: false,
                returnTaskList: [],  // 回退列表数据
                // 退回任务标签当前活跃id
                returnTaskActiveId: "",

                // 退回上级弹窗是否打开
                rejectOpen: false,

                // 退回初始弹框是否打开
                returnFirstOpen: false,

                // 处理意见
                comment: ""

            }
        },
        onLoad: function (options) {
            let taskDefKey = undefined;
            if (options) {
                this.deployId = options.deployId;
                this.procInsId = options.procInsId;
                this.taskId = options.taskId;
                this.procDefId = options.procDefId;
                this.startUserId = options.startUserId;
                taskDefKey = options.taskDefKey;
            }

            // 获取登录id
            this.loginUserId = store.state.user.id;
            

            // 获取开始节点信息，并且判断当前是否为填写节点
            getBpmnStartId(this.procDefId).then(response => {
                let currentKey = response.msg;
                if (taskDefKey == currentKey) {
                    this.hasFillNode = true;
                } else {
                    this.hasFillNode = false;
                }
            })

            // 获取获取表单变量信息
            this.getFormVariable(this.procInsId).then(() => {
                // 获取流程表单信息并且导入
                this.getFormPathAndImport(this.deployId);
            });

            // 获取流转记录
            this.getFlowRecordList(this.procInsId, this.deployId);

            // 获取窗口高度
            this.getWindowHeight();

            // 监听保存表单
            uni.$once('saveForm', form => {
                this.saveForm(form);
            })


        },
        methods: {

            // 获取窗口高度
            getWindowHeight() {
                getWindowHeight().then(response => {
                    this.windowHeight = response;
                })
            },

            /** 流程流转记录 */
            getFlowRecordList(procInsId, deployId) {
                const params = {
                    procInsId: procInsId,
                    deployId: deployId
                };
                flowRecord(params).then(response => {
                    let flowRecordList = response.data.flowList;
                    this.lastFlowRecord = flowRecordList.splice(flowRecordList.length - 1, 1)[0];
                    this.flowRecordList = flowRecordList;
                })
            },

            // 处理标签点击操作
            handleTabsClick(item) {
                let index = item && item.index;
                switch (index) {
                    case 0:
                        this.flowRecordShow = false;
                        this.flowableShow = false;
                        this.formShow = true;
                        break;
                    case 1:
                        this.flowableShow = false;
                        this.formShow = false;
                        this.flowRecordShow = true;
                        break;
                    case 2:
                        // 获取流程图xml
                        this.getFlowableXml();
                        break;
                }
            },

            // 获取表单变量信息
            getFormVariable(procInsId) {
                return new Promise((resolve, reject) => {
                    this.$modal.loading("正在获取数据...")
                    getFormVariableList({ procInsId }).then(response => {
                        let data = response.data;
                        let formData = getFormData(data);
                        this.saveformIdObj(data);

                        this.componentForm = formData;
                        this.$modal.closeLoading();
                        resolve();
                    })
                })

            },

            // 将表表单id按照名称保存在对象中
            saveformIdObj(data) {
                let formIdObj = this.formIdObj;
                data.forEach(element => {
                    formIdObj[element.varName] = element.varId;
                });
            },

            // 获取流程图Xml
            getFlowableXml() {

                flowXmlAndNode({
                    procInsId: this.procInsId, deployId: this.deployId
                }).then(res => {
                    this.formShow = false;
                    this.flowRecordShow = false;
                    this.flowableShow = true;
                    this.flowData = res.data;
                })
            },

            // 导入组件
            importComponent(componentPath) {
                if (!componentPath) {
                    return;
                }
                let prefixIndex = componentPath.indexOf("@/");
                let suffixIndex = componentPath.lastIndexOf(".vue");
                if (prefixIndex == -1) {
                    prefixIndex = 0;
                } else {
                    prefixIndex = 2;
                }
                if (suffixIndex == -1) {
                    suffixIndex = componentPath.length;
                }

                let path = componentPath.substring(prefixIndex, suffixIndex);
                let appPath = path.replace("views/", "pages/");

                // #ifdef H5
                this.currentComponent = resolve => require([`@/${appPath}.vue`], resolve);
                // #endif

                // #ifdef MP-WEIXIN || APP-PLUS
                this.currentComponentPath = `@/${appPath}.vue`;
                // #endif

            },

            // 获取表单信息并且导入
            getFormPathAndImport(deployId) {
                getFlowableFormByDeployId(deployId).then(response => {
                    let data = response.data;
                    this.importComponent(data.formPath);
                })
            },

            /** 申请流程表单数据提交 */
            submitCurrentForm(hasStart) {
                this.hasStart = hasStart;
                this.$refs.currentComponent.submitForm();
            },

            // 保存表单
            saveForm(form) {
                let formIdObj = this.formIdObj;
                let itemList = [];
                for (const key in form) {
                    if (Object.hasOwnProperty.call(form, key)) {
                        let eachObj = {};
                        const element = form[key];
                        eachObj["name"] = key;
                        eachObj["type"] = getVarType(element);
                        if (eachObj["type"] == "array") {
                            eachObj["value"] = JSON.stringify(element);
                        } else {
                            eachObj["value"] = element;
                        }

                        // 如果有id进行保存
                        if (Object.hasOwnProperty.call(formIdObj, key)) {
                            eachObj["id"] = formIdObj[key];
                        }

                        itemList.push(eachObj);
                    }
                }


                // 如果只是保存，不需要启动
                if (!this.hasStart) {
                    let currentData = {
                        itemList,
                        procInsId: this.procInsId
                    }
                    updateFormVariableList(currentData).then(response => {
                        // 显示成功信息，并且返回页面
                        this.showSuccessMessageAndGoBack(response.msg);
                    })
                    return;
                }

                const params = { taskId: this.taskId };
                getNextFlowNode(params).then(res => {
                    const data = res.data;
                    if (data) {
                        // 如果启动，设置意见
                        this.comment = "启动流程";

                        // 设置表单信息
                        this.taskComplete(itemList);
                    }
                })
            },

            // 显示错误显示提示
            showErrorToast(message) {
                this.$refs.uToast.show({
                    type: "error",
                    message,
                    duration: 1500,
                    position: "top"
                });
            },

            /** 用户审批任务 */
            taskComplete(itemList) {
                let comment = this.comment;
                if (!comment || comment == "") {
                    // 提示信息
                    this.showErrorToast("请填写处理意见");
                    return;
                }

                let instanceId = this.procInsId;
                let taskId = this.taskId;
                let taskForm = {
                    instanceId,
                    taskId,
                    comment
                }
                if (itemList) {
                    taskForm["itemList"] = itemList;
                }
                complete(taskForm).then(response => {
                    // 关闭弹窗
                    this.completeOpen = false;
                    // 显示成功信息，并且返回页面
                    this.showSuccessMessageAndGoBack(response.msg);
                });

            },

            /** 加载审批任务弹框 */
            handleComplete() {
                this.comment = "";
                this.completeOpen = true;
            },

            /** 可退回任务列表 */
            handleReturn() {
                // 重置
                this.comment = "";
                this.returnTaskActiveId = "";

                let taskId = this.taskId;
                let taskForm = {
                    taskId
                }
                returnList(taskForm).then(res => {
                    this.returnTaskList = res.data;
                    this.returnOpen = true;
                })
            },

            // 处理退回标签点击
            handleReturnTagClick(name) {
                this.returnTaskActiveId = name;
            },

            /** 提交退回任务 */
            taskReturn() {
                // 不选择退回节点提示错误信息
                let returnTaskActiveId = this.returnTaskActiveId;
                if (!returnTaskActiveId && returnTaskActiveId == "") {
                    this.showErrorToast("请选择退回节点");
                    return;
                }

                // 不填写处理意见提示错误信息
                let comment = this.comment;
                if (!comment || comment == "") {
                    this.showErrorToast("请填写处理意见");
                    return;
                }


                let taskId = this.taskId;
                let targetKey = this.returnTaskActiveId;
                let taskForm = {
                    taskId,
                    targetKey,
                    comment
                };
                returnTask(taskForm).then(response => {
                    // 关闭弹窗
                    this.returnOpen = false;
                    // 显示成功信息，并且返回页面
                    this.showSuccessMessageAndGoBack(response.msg);
                });
            },

            // 显示成功信息，并且返回页面
            showSuccessMessageAndGoBack(message) {
                let delayTime = 1000;
                // 返回上层页面
                this.$modal.msgSuccess(message);
                // #ifdef MP-WEIXIN || APP-PLUS
                delayTime = 500;
                // #endif
                // 设置延迟，防止提示信息不显示
                setTimeout(() => {
                    // 返回上一页
                    this.$tab.navigateBack();
                }, delayTime)
            },

            /** 驳回任务 */
            handleReject() {
                this.comment = "";
                this.rejectOpen = true;

            },
            /** 驳回任务 */
            taskReject() {
                // 不填写驳回意见提示错误信息
                let comment = this.comment;
                if (!comment || comment == "") {
                    this.showErrorToast("请填写驳回意见");
                    return;
                }
                let taskId = this.taskId;
                let taskForm = {
                    taskId,
                    comment
                }
                rejectTask(taskForm).then(response => {
                    // 关闭弹窗
                    this.rejectOpen = false;
                    // 显示成功信息，并且返回页面
                    this.showSuccessMessageAndGoBack(response.msg);
                });
            },

            // 处理点击退回到初始节点操作
            handleReturnFirst() {
                this.comment = "";
                this.returnFirstOpen = true;
            },

            // 提交退回初始任务
            taskFirstReturn() {
                let comment = this.comment;
                if (!comment || comment == "") {
                    this.showErrorToast("请填写退回意见");
                    return;
                }
                let taskId = this.taskId;
                let taskForm = {
                    targetKey: "start_event",
                    taskId,
                    comment
                }
                returnTask(taskForm).then(response => {
                    // 关闭弹窗
                    this.returnFirstOpen = false;
                    // 显示成功信息，并且返回页面
                    this.showSuccessMessageAndGoBack(response.msg);
                });
            },

        },
    }
</script>

<style lang="css" scoped>
    .py-flow-content {
        overflow: auto;
    }

    /* 弹窗按钮样式 */
    .py-popup-button-group {
        margin-top: 5px;
        display: flex;
        justify-content: space-between;
    }

    .py-popup-button-group uni-button {
        margin: 0 5px;
    }

    .py-return-tag-group {
        display: flex;
        /* 允许换行 */
        flex-wrap: wrap;
    }

    .py-return-tag-group .py-tag {
        margin: 5px 5px 0 0;
    }
</style>